/*
 * ServerCorePost.java
 *
 * Created on January 11, 2007, 3:43 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.sf.iSnake.server;

import java.util.Vector;
import net.sf.iSnake.core.*;

/**
 * @author Suraj
 */
public class ServerCorePost extends Thread{
    private ServerCorePre ServerPre=null;
    private ServerNetworkInterface serverInterface=null;
    private PostModePacketSender postModeSender=null;
    private int thisClient;
    private Object obj;
    private boolean handle=false; //false==No data to process
    
    //processing variables
    private Short[][] startXY;       //starting x coordinate of all the clients
    private Short[][] currentXY;     //Current x coordinate of all the clients
    private Short[] life;
    private long[] score;
    private Short[] foodXY;
    private Short gameSpeed;
    private postmodeISCPpacketForSend postISCPget;
    
    private postmodeISCPpacketForMulticast postISCPsend;
    private Short[][] dxdy;
    
    private Short[] getFood(){
        return null;
    }
    
    /**
     * Sets the ServerNetworkInterface
     *
     * @param serverInterface An instance of ServerNetworkInterface
     */
    public void setServerInterface(ServerNetworkInterface ClientServer){
        this.serverInterface=ClientServer;
    }
    /** Creates a new instance of ServerCorePost
     *@param ServerPre The Pre-Mode server
     */
    public ServerCorePost(ServerCorePre ServerPre,ServerNetworkInterface ClientServer) {
        this.ServerPre=ServerPre;
        this.startXY=new Short[ServerPre.getMAX_CLIENT()][2];
        this.currentXY=new Short[ServerPre.getMAX_CLIENT()][2];
        this.life=new Short[ServerPre.getMAX_CLIENT()];
        this.score=new long[ServerPre.getMAX_CLIENT()];
        this.foodXY=new Short[2];
        gameSpeed=new Short("400");
        postISCPget=new postmodeISCPpacketForSend();
        
        this.resetLifeAndScore();
        this.serverInterface=ClientServer;
        this.postModeSender=new PostModePacketSender(this);
        this.dxdy=new Short[ServerPre.getMAX_CLIENT()][2];
        
    }
    /**
     * Creates a new instance of ServerCorePost .
     *  An instance of ServerNetworkInterface shoule be set Later via public void setServerInterface(ServerNetworkInterface serverInterface);
     */
    public ServerCorePost(ServerCorePre ServerPre) {
        this.ServerPre=ServerPre;
        this.startXY=new Short[ServerPre.getMAX_CLIENT()][2];
        this.currentXY=new Short[ServerPre.getMAX_CLIENT()][2];
        this.life=new Short[ServerPre.getMAX_CLIENT()];
        this.score=new long[ServerPre.getMAX_CLIENT()];
        this.foodXY=new Short[2];
        gameSpeed=new Short("400");
        postISCPget=new postmodeISCPpacketForSend();
        
        this.resetLifeAndScore();
        this.postModeSender=new PostModePacketSender(this);
        this.dxdy=new Short[ServerPre.getMAX_CLIENT()][2];
    }
    public synchronized void run(){
        System.gc();
        ServerPre.status(ServerStatus.DEBUG_INFO,"Done receving the sync. signal...");
        for (int j=0;j<10;j++)
            currentXY[j]=this.myCloner(startXY[j]);
        //STEP 3: Send the second Synchronization pulse
        //Signal : POST_CMD_SynchronizeClient
        this.postISCPsend=new postmodeISCPpacketForMulticast();
        postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_SynchronizeClient);
        serverInterface.send(postISCPsend);
        ServerPre.status(ServerStatus.DEBUG_INFO,"Sync. signal send from server...");
        
        //send the Food Coordinate
        ServerPre.status(ServerStatus.DEBUG_INFO,"Sending Food Coordinates...");
        this.postISCPsend=new postmodeISCPpacketForMulticast();
        postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_MULTICAST_CURRENT_FOOD);
        //this.foodXY=ServerPre.getWallGen().getFood(this.currentXY);
        Short[] food=new Short[2];
        food=ServerPre.getWallGen().getFood(this.currentXY);
        postISCPsend.setCurrentFood(new GameAreaCoordinate(food[0],food[1]));
        this.foodXY[0]=food[0];
        this.foodXY[1]=food[1];
        serverInterface.send(postISCPsend);
        ServerPre.status(ServerStatus.DEBUG_INFO,"Food Coordinates send...");
        
        initDxDy();
        //STEP 4: send Final Synchronization pulse
        //Signal : PRE_CMD_GameStartPulse
        this.postISCPsend=new postmodeISCPpacketForMulticast();
        postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_GameStartPulse);
        serverInterface.send(postISCPsend);
        ServerPre.status(ServerStatus.DEBUG_INFO,"\"Game Start Pulse\" Send...");
        //start the postModePacketSender Here
        PostModePacketSender sth=new PostModePacketSender(this);
        postISCPsend=new postmodeISCPpacketForMulticast();
        postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_MULTICAST_DXDY);
        ServerPre.status(ServerStatus.DEBUG_INFO,"The Game is started...");
        while(ServerPre.isPostMode()){
            ServerPre.status(ServerStatus.DEBUG_MESSAGE,"Handle = "+handle);
            if(handle){
                //TODO Process the Client data here during Post sesion
                
                postISCPget=(postmodeISCPpacketForSend) obj;
                if(postISCPget.getPostmodeCommandSend().equals(ISCP.POST_CMD_SEND_dxdy)){
                    dxdy[thisClient][0]=postISCPget.getDx();
                    dxdy[thisClient][1]=postISCPget.getDy();
                    ServerPre.status(ServerStatus.DEBUG_MESSAGE,"DxDy Received from: "+postISCPget.getPlayer_id()+"                        dx= "+postISCPget.getDx()+", dy="+postISCPget.getDy());
                } else if(postISCPget.getPostmodeCommandSend().equals(ISCP.POST_CMD_SEND_life)){
                    //update the Clients life
                    //send it to all
                } else if(postISCPget.getPostmodeCommandSend().equals(ISCP.POST_CMD_SEND_score)){
                    //update the score
                } else {
                    ServerPre.status(ServerStatus.DEBUG_MESSAGE,"Post Mode Command Received: "+postISCPget.getPostmodeCommandSend()+" From Player: "+postISCPget.getPlayer_id());
                }
                //if level change stop the postModePacketSenderHere and assign it with null value
                handle=false;
                notifyAll();
            }
            
            else{
                try {
                    wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
    
    /* Sends the data to post-server to process
     * @param Client The client No that sends the data
     * @param obj The object to process
     */
    public synchronized void forwardPacket(int c,Object obj){
        while(ServerPre.isPostMode()){
            if (!handle){
                this.thisClient=c;
                this.obj=obj;
                handle=true;
                break;
            } else{
                try {
                    wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        notifyAll();
    }
    
    public void sendDxDy(){
        int g=0;
        boolean b=false;
        Short no=new Short("0");
        postISCPsend =new postmodeISCPpacketForMulticast();
        postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_MULTICAST_DXDY);
        for (int i=1;i<ServerPre.getMAX_CLIENT();i++){
            if(ServerPre.isPlayer(i)){
                g=this.updateNCheck(i);
                System.out.println("******************************Current Coordinate of snake "+i+" = ( "+currentXY[i][0]+", "+currentXY[i][1]+")");
                if(g==1){
                    b=true;
                    no=Short.parseShort(""+i);
                } else if(g==2){
                    System.out.println("Snake "+i+" Striked on wall.......from server............................................................");
                    postISCPsend.setSnakeCollided(true);
                    postISCPsend.setCollidedPlayers(new Short(""+i));
                    this.currentXY[i]=this.startXY[i].clone() ;
                    System.out.println("Done reseting the snake start position for "+i+" from  ( "+currentXY[i][0]+", "+currentXY[i][1]+") to ( "+startXY[i][0]+", "+startXY[i][1]+")");
                    this.life[i]--;
                    this.dxdy[i][0]=0;
                    this.dxdy[i][1]=0;
                }
            }
        }
        postISCPsend.setPlayersDxDy(dxdy);
        if(b){
            //food Consumed
            postISCPsend.setPostmodeMulticastCommand(ISCP.POST_CMD_MULTICAST_FOOD_CONSUMED_BY);
            postISCPsend.setFoodConsumedBy(no);
            Short[] food=new Short[2];
            food=ServerPre.getWallGen().getFood(this.currentXY);
            ServerPre.status(ServerStatus.DEBUG_INFO,"                                     New food at : x= "+food[0]+", y= "+food[1]);
            postISCPsend.setCurrentFood(new GameAreaCoordinate(food[0],food[1]));
            this.foodXY=food;
            //also add the new food here
        }
        serverInterface.send(postISCPsend);
//       ServerPre.status(ServerStatus.DEBUG_MESSAGE,"DxDy Send...");
    }
    
    public void setStartXY(Vector v) {
        for (int i=0;i<v.size();i++){
            this.startXY[i][0]=((GameAreaCoordinate)v.get(i)).getX();
            this.startXY[i][1]=((GameAreaCoordinate)v.get(i)).getY();
        }
    }
    
    public ServerCorePre getServerPre() {
        return ServerPre;
    }
    
    private void initDxDy(){
        for(int i=0;i<ServerPre.getMAX_CLIENT();i++){
            if(ServerPre.isPlayer(i)){
                dxdy[i][0]=0;
                dxdy[i][1]=0;
            } else{
                dxdy[i][0]=-1;
                dxdy[i][1]=-1;
            }
        }
    }
    
    private void resetLifeAndScore(){
        for (int i=0;i<ServerPre.getMAX_CLIENT();i++){
            if(ServerPre.isPlayer(i)){
                this.life[i]=5;
                this.score[i]=0;
            } else{
                this.life[i]=-1;
                this.score[i]=-1;
            }
        }
    }
    
    public Short getGameSpeed() {
        return gameSpeed;
    }
    
    public void setGameSpeed(Short gameSpeed) {
        this.gameSpeed = gameSpeed;
    }
    
    public int updateNCheck(int client) {
        this.currentXY[client][0]=new Short(this.currentXY[client][0].intValue()+this.dxdy[client][0].intValue()+"");
        this.currentXY[client][1]=new Short(this.currentXY[client][1].intValue()+this.dxdy[client][1].intValue()+"");
        if(this.foodXY[0].equals(this.currentXY[client][0]) && this.foodXY[1].equals(this.currentXY[client][1])){
            this.currentXY[client][0]=new Short(this.currentXY[client][0].intValue()-this.dxdy[client][0].intValue()+"");
            this.currentXY[client][1]=new Short(this.currentXY[client][1].intValue()-this.dxdy[client][1].intValue()+"");
            return 1;
        } else if(!ServerPre.getWallGen().isSnakeValid(currentXY[client])){
            return 2;
        } else if(this.currentXY[client][0].equals(new Short("-1")) || this.currentXY[client][0].equals(new Short("64")) || this.currentXY[client][1].equals(new Short("-1")) || this.currentXY[client][1].equals(new Short("48"))){
            return 2;
        } else return 0;
    }
    
    public Short[] myCloner(Short [] s){
        return s.clone();
    }
}
